<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { SPEED, SpeedModel, SpeedUnit, speedUnitName } from './speed-util'
import { ifNaNOrNull } from './number-util'

type Props = {
  modelValue: number | undefined
  defaultUnit?: SpeedUnit
  optional?: boolean
  min?: number
  max?: number
  disabled?: boolean
  invalidValue?: number
}

const props = withDefaults(defineProps<Props>(), {
  defaultUnit: SpeedUnit.MPS,
  optional: false,
  disabled: false,
  invalidValue: SPEED.NONE
})

const emits = defineEmits<{
  (e: 'update:modelValue', v: number): void
}>()

let spdModel = SPEED
function initSpdModel() {
  if (props.invalidValue !== SPEED.NONE) {
    spdModel = new SpeedModel(props.invalidValue)
  }
}

let innerValue: number = 0
const str = ref<string | number>('')
let unit = SpeedUnit.MPS
const unitName = ref<string>(speedUnitName(unit))
const ph = computed(() => (props.optional ? '选填' : '必填'))
const ok = ref<boolean>(true)
function checkOk() {
  ok.value = doCheckOk()
}

function doCheckOk(): boolean {
  if (innerValue === undefined) {
    return props.optional
  }
  if (isNaN(innerValue)) {
    return false
  }
  if (spdModel.invalid(innerValue)) {
    return props.optional
  }
  if (props.min != null && innerValue < props.min) {
    return false
  }
  if (props.max != null && innerValue > props.max) {
    return false
  }
  return true
}

function init() {
  initSpdModel()
  unit = props.defaultUnit
  unitName.value = speedUnitName(unit)
  innerValue = ifNaNOrNull(props.modelValue, spdModel.NONE)
  str.value = spdModel.mps2str(innerValue, unit)
  checkOk()
}

function onInput() {
  if (typeof str.value === 'number') {
    innerValue = spdModel.toMps(str.value, unit)
  } else {
    innerValue = spdModel.str2mps(str.value, unit)
  }
  checkOk()
  if (innerValue !== props.modelValue) {
    emits('update:modelValue', innerValue)
  }
}

function onModelValue() {
  const v = props.modelValue
  if (v === innerValue) {
    return
  }
  innerValue = ifNaNOrNull(v, spdModel.NONE)
  str.value = spdModel.mps2str(innerValue, unit)
  checkOk()
}

function updateUnit() {
  if (props.disabled) {
    return
  }
  if (unit === SpeedUnit.MPS) {
    unit = SpeedUnit.KMPH
  } else if (unit === SpeedUnit.KMPH) {
    unit = SpeedUnit.KT
  } else if (unit === SpeedUnit.KT) {
    unit = SpeedUnit.FTPM
  } else {
    unit = SpeedUnit.MPS
  }
  unitName.value = speedUnitName(unit)
  str.value = spdModel.mps2str(innerValue, unit)
}

onMounted(() => init())
watch(() => props.modelValue, onModelValue)
</script>

<template>
  <div class="speed-input">
    <input
      v-model="str"
      @input="onInput"
      type="number"
      class="input"
      :class="{ 'is-danger': !ok }"
      :disabled="disabled"
      :placeholder="ph"
    />
    <span class="unit" :class="{ 'is-disabled': disabled }" @click="updateUnit">
      {{ unitName }}
    </span>
  </div>
</template>
